package com.cy.store.controller;

import com.cy.store.controller.ex.*;
import com.cy.store.entity.User;
import com.cy.store.service.IUserService;
import com.cy.store.service.ex.InsertException;
import com.cy.store.service.ex.UsernameDuplicatedException;
import com.cy.store.util.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/*
 * @Author: jun
 * @Date:2022/11/2 10:47
 * @概述：
 */
//@Controller
@RestController //这个注解的功能等效于@Controller+@ResponseBody
@RequestMapping("users")
public class UserController extends BaseController{
    @Autowired
    private IUserService userService;

    /**
     * 注册层
     * @param user
     * @return
     */
    @RequestMapping("reg")
    public JsonResult<Void> reg(User user){
        userService.reg(user);
        return new JsonResult<>(OK);//则里尖括号爆红显示java无法推断com.store.util.JsonResult<>的类型参数，
        // 解决办法：在JsonResult中重写public JsonResult（Integer state)方法
    }
    
    //优化后以下代码注释掉
//    @RequestMapping("reg")
////    @ResponseBody   //表示此方法的响应结果以json格式进行数据的响应给到前端，比较麻烦
//    public JsonResult<Object> reg(User user){
//        //创建响应返回的结果对象
//        JsonResult<Object> jsonResult = new JsonResult<>();
//        try {
//            userService.reg(user);
//            jsonResult.setState(200);   //注册成功状态码为200
//            jsonResult.setMessage("用户注册成功");    //提示成功
//        } catch (UsernameDuplicatedException e) {
//            jsonResult.setState(4000);  //当用户名被占用时，设置状态码为4000
//            jsonResult.setMessage("用户名被占用");    //设置描述信息
//        } catch (InsertException e){
//            jsonResult.setState(5000);    //插入数据异常,设置状态码为5000
//            jsonResult.setMessage("注册时产生未知的异常");
//        }
//        return jsonResult;
//    }


    /**
     * 登录控制层
     * @param username
     * @param password
     * @return
     */
    @RequestMapping("login")
    public JsonResult<User> login(String username, String password,HttpSession session){
        User data = userService.login(username, password);
        //这里的数据如何转移到session对象里？,向session对象中完成数据的绑定（session全局的）
        session.setAttribute("uid",data.getUid());
        session.setAttribute("username",data.getUsername());

        //获取session中绑定的数据
        System.out.println("id:"+getuidFromSession(session));
        System.out.println("username:"+getUsernameFromSession(session));

        return new JsonResult<User>(OK,data);
    }

    /**
     * 修改页面控制层
     * @param oldPassword
     * @param newPassword
     * @param session
     * @return
     */
    @RequestMapping("change_password")
    public JsonResult<Void> changPassword(String oldPassword,
                                          String newPassword,
                                          HttpSession session){
        Integer uid = getuidFromSession(session);
        String username = getUsernameFromSession(session);
        userService.changePassword(uid,username,oldPassword,newPassword);
        return new JsonResult<>(OK);
    }

    @RequestMapping("get_by_uid")
    public JsonResult<User> getByUid(HttpSession session){
        //从session中拿数据
        User data = userService.getByUid(getuidFromSession(session));
        return new JsonResult<>(OK,data);
    }

    @RequestMapping("change_info")
    public JsonResult<Void> changeInfo(User user,
                                       HttpSession session){
        //user对象有四个部分的数据：username、phone、email、gender
        //uid数据需要再次封装到user对象中
        Integer uid = getuidFromSession(session);
        String username = getUsernameFromSession(session);
        //这里的username必须要有，因为最后的修改人需要用，要得知道修改人是谁。
        userService.changeInfo(uid,username,user);
        //继续返回一个合适的Json结果，告诉用户操作成功了
        return new JsonResult<>(OK);
    }

    //设置上传文件的最大值为10M
    public static final int AVATAR_MAX_SIZE = 10*1024*1024;
    //设置上传文件的类型
    public static final List<String> AVATAR_TYPE = new ArrayList<>();
    static {
        AVATAR_TYPE.add("image/jpeg");
        AVATAR_TYPE.add("image/png");
        AVATAR_TYPE.add("image/bmp");
        AVATAR_TYPE.add("image/gif");
    }
    /**
     * MultipartFile接口是SpringMVC提供的一个接口，这个接口为我们包装了
     * 获取文件类型的数据（任何类型的file都可以接收），SpringBoot它整合了SpringMVC，只需要在
     * 处理请求的方法参数列表上声明一个参数类型为MultipartFile的参数，然后SpringBoot自动将
     * 传递给服务的文件数据赋值给这个参数
     *
     * @RequestParam("file") 表示请求中的参数，将请求中的参数注入请求的处理方法的某个参数上，
     * 如果名称不一致则可以使用@RequestParam注解进行标记和映射
     *
     * @param session
     * @param file
     * @return
     */
    @RequestMapping("change_avatar")
    public JsonResult<String> changeAvatar(HttpSession session,
                                           @RequestParam("file") MultipartFile file){
        //判断文件是否为空
        if (file.isEmpty()){
            throw new FileEmptyException("文件为空");
        }
        if (file.getSize()>AVATAR_MAX_SIZE){
            throw new FileSizeException("文件超出大小");
        }
        //判断文件的类型是否是我们规定的和点后缀类型
        String contentType = file.getContentType();
        if (!AVATAR_TYPE.contains(contentType)){
            throw new FileTypeException("文件类型不支持");
        }
        //上传的文件
        String parent = session.getServletContext().getRealPath("upload");
        //File对象指向这个路径，File是否存在
        File dir = new File(parent);
        if (!dir.exists()){//检测目录是否存在
            dir.mkdirs();//创建当前的目录
        }
        //获取到文件的名称，使用UUID工具类生成一个新的字符串作为文件名
        //例如：avatar01.png
        String originalFilename = file.getOriginalFilename();
        System.out.println("originalFilename:"+originalFilename);
        //定位到.的位置
        int index = originalFilename.lastIndexOf(".");
        //
        String suffix = originalFilename.substring(index);

        String filename = UUID.randomUUID().toString().toUpperCase()+suffix;
        File dest = new File(dir, filename);//是一个空文件
        //参数file中数据写入到这个空文件中
        try {
            file.transferTo(dest);  //将file文件中的数据写入到dest文件中
        } catch (FileStateException e){
          throw new FileStateException("文件状态异常");
        } catch (IOException e) {
            throw new FileUploadIOException("文件读写异常");
        }

        //调用头像的修改
        Integer uid = getuidFromSession(session);
        String username = getUsernameFromSession(session);
        //返回头像的路径/upload/test.png
        String avatar = "/upload/"+filename;
        userService.changeAvatar(uid,avatar,username);
        //返回用户的头像的路径给前端页面，将来用于头像展示使用
        return new JsonResult<>(OK,avatar);
    }
}
